1 About

1.1 Contributions

Please note that authorship is alphabetical. Contributions are listed below - see github for details and who to blame for what :-).

1.3 Citation

If you wish to refer to any of the material from this report please cite as:

  • Anderson, B., (2020) Air Quality in Southampton (UK): Exploring the effect of UK covid 19 lockdown on air quality , University of Southampton: Southampton, UK.

Report circulation:

  • Public

Report purpose:

This work is (c) 2020 the University of Southampton.

1.4 Disclaimer

I usually do energy demand research but in the absence of access to real time demand data on lockdown (unlike during the World Cup) I’m looking at other things.

2 Introduction

Data for Southampton downloaded from :

Southampton City Council collects various forms of air quality data at the sites shown in 2.1. Some of these sites feed data to AURN. The AURN data then undergoes a manual check and ratification process.

WHO publishes information on the health consequences and “acceptable” exposure levels for each of these.

Data health warning

The southampton.my-air.uk data used is not cleaned or tested for measurement error. The AURN from https://uk-air.defra.gov.uk/ has been ratified if it is more than 6 months old.

For much more detailed analysis see a longer and very messy data report.

sotonAirDT <- sotonAirDT[obsDate > as.Date("2019-01-01")]  # for speed
sotonAirDT[, `:=`(obsDate, lubridate::date(dateTimeUTC))]
sotonAirDT[, `:=`(site, ifelse(site == "Southampton A33", "Southampton A33 AURN data", site))]
sotonAirDT[, `:=`(site, ifelse(site == "Southampton Centre", "Southampton Centre AURN data", site))]
t <- sotonAirDT[!is.na(value), .(from = min(dateTimeUTC), to = max(dateTimeUTC), nObs = .N, nPollutants = uniqueN(pollutant)), 
    keyby = .(site, source)]

kableExtra::kable(t, caption = "Dates data != NA available by site and measure", digits = 2) %>% kable_styling()
Table 2.1: Dates data != NA available by site and measure
site source from to nObs nPollutants
Southampton - A33 Roadside (near docks, AURN site) southampton.my-air.uk 2019-01-02 2020-04-03 07:00:00 20003 2
Southampton - Background (near city centre, AURN site) southampton.my-air.uk 2019-01-02 2020-04-03 07:00:00 50767 5
Southampton - Onslow Road (near RSH) southampton.my-air.uk 2019-01-02 2020-03-31 09:00:00 20353 2
Southampton - Victoria Road (Woolston) southampton.my-air.uk 2019-01-02 2020-04-01 06:00:00 13022 2
Southampton A33 AURN data AURN 2020-01-01 2020-04-02 23:00:00 15189 8
Southampton Centre AURN data AURN 2020-01-01 2020-04-02 23:00:00 19720 9

3 Analysis

In this section we present graphical analysis of the previoulsy downloaded data. Note this is just a snapshot of the data available.

3.1 Nitrogen Dioxide (no2)

From WHO: https://www.who.int/news-room/fact-sheets/detail/ambient-(outdoor)-air-quality-and-health

"As an air pollutant, NO2 has several correlated activities. At short-term, concentrations exceeding 200 μg/m3, it is a toxic gas which causes significant inflammation of the airways.

NO2 is the main source of nitrate aerosols, which form an important fraction of PM2.5 and, in the presence of ultraviolet light, of ozone. The major sources of anthropogenic emissions of NO2 are combustion processes (heating, power generation, and engines in vehicles and ships).

Health effects

Epidemiological studies have shown that symptoms of bronchitis in asthmatic children increase in association with long-term exposure to NO2. Reduced lung function growth is also linked to NO2 at concentrations currently measured (or observed) in cities of Europe and North America."

yLab <- "Nitrogen Dioxide (ug/m3)"
no2dt <- sotonAirDT[pollutant == "no2"]
t <- no2dt[!is.na(value), .(mean = mean(value, na.rm = TRUE), sd = sd(value, na.rm = TRUE), min = min(value, 
    na.rm = TRUE), max = max(value, na.rm = TRUE), minDate = min(obsDate), maxDate = max(obsDate)), keyby = .(site, 
    source)]
kableExtra::kable(t, caption = "Summary of NO2 data") %>% kable_styling()
Table 3.1: Summary of NO2 data
site source mean sd min max minDate maxDate
Southampton - A33 Roadside (near docks, AURN site) southampton.my-air.uk 29.85441 21.65616 0.00000 155.3000 2019-01-02 2020-04-03
Southampton - Background (near city centre, AURN site) southampton.my-air.uk 27.40359 16.77908 2.30000 144.2000 2019-01-02 2020-04-03
Southampton - Onslow Road (near RSH) southampton.my-air.uk 40.41641 19.73466 3.30000 144.5000 2019-01-02 2020-03-31
Southampton - Victoria Road (Woolston) southampton.my-air.uk 32.43783 20.57356 0.00000 147.7000 2019-01-02 2020-04-01
Southampton A33 AURN data AURN 28.96356 21.02939 -2.14200 106.4593 2020-01-01 2020-04-02
Southampton Centre AURN data AURN 24.88599 16.32597 1.90581 128.2762 2020-01-01 2020-04-02

Table 3.1 suggests that there may be a few (9) negative values.

Figure 3.1 shows the most recent hourly data.

recentDT <- no2dt[!is.na(value) & obsDate > myParams$recentCutDate]
p <- makeDotPlot(recentDT, xVar = "dateTimeUTC", yVar = "value", byVar = "site", yLab = yLab)

p <- p + scale_x_datetime(date_breaks = "2 day", date_labels = "%a %d %b") + theme(axis.text.x = element_text(angle = 90, 
    hjust = 1)) + labs(caption = paste0(myParams$gamCap, myParams$lockdownCap, myParams$weekendCap))

# final plot - adds annotations
yMin <- min(recentDT$value)
yMax <- max(recentDT$value)

p <- addLockdownDateTime(p)
addWeekendsDateTime(p)
Nitrogen Dioxide levels, Southampton (hourly, recent)

Figure 3.1: Nitrogen Dioxide levels, Southampton (hourly, recent)

Beware seasonal trends and weather effects

3.2 Oxides of Nitrogen (nox)

yLab <- "Oxides of Nitrogen (ug/m3)"
noxdt <- sotonAirDT[pollutant == "nox"]
t <- noxdt[!is.na(value), .(mean = mean(value, na.rm = TRUE), sd = sd(value, na.rm = TRUE), min = min(value, 
    na.rm = TRUE), max = max(value, na.rm = TRUE), minDate = min(obsDate), maxDate = max(obsDate)), keyby = .(site, 
    source)]
kableExtra::kable(t, caption = "Summary of NOx data") %>% kable_styling()
Table 3.2: Summary of NOx data
site source mean sd min max minDate maxDate
Southampton - Onslow Road (near RSH) southampton.my-air.uk 78.66165 68.85744 4.60000 719.7000 2019-01-02 2020-03-31
Southampton - Victoria Road (Woolston) southampton.my-air.uk 67.84672 74.29603 1.10000 848.1000 2019-01-02 2020-04-01
Southampton A33 AURN data AURN 69.56498 68.59654 0.19699 536.7503 2020-01-01 2020-04-02
Southampton Centre AURN data AURN 41.97340 54.64460 2.29213 855.6162 2020-01-01 2020-04-02

Table 3.2 suggests that there may be a few (0) negative values.

Figure 3.2 shows the most recent hourly data.

recentDT <- noxdt[!is.na(value) & obsDate > myParams$recentCutDate]
p <- makeDotPlot(recentDT, xVar = "dateTimeUTC", yVar = "value", byVar = "site", yLab = yLab)

p <- p + scale_x_datetime(date_breaks = "2 day", date_labels = "%a %d %b") + theme(axis.text.x = element_text(angle = 90, 
    hjust = 1)) + labs(caption = paste0(myParams$gamCap, myParams$lockdownCap, myParams$weekendCap))

# final plot - adds annotations
yMin <- min(recentDT$value)
yMax <- max(recentDT$value)

p <- addLockdownDateTime(p)

addWeekendsDateTime(p)
Oxides of nitrogen levels, Southampton (hourly, recent)

Figure 3.2: Oxides of nitrogen levels, Southampton (hourly, recent)

Beware seasonal trends and weather effects

3.3 Sulphour Dioxide

From WHO: https://www.who.int/news-room/fact-sheets/detail/ambient-(outdoor)-air-quality-and-health

"SO2 is a colourless gas with a sharp odour. It is produced from the burning of fossil fuels (coal and oil) and the smelting of mineral ores that contain sulfur. The main anthropogenic source of SO2 is the burning of sulfur-containing fossil fuels for domestic heating, power generation and motor vehicles.

Health effects

SO2 can affect the respiratory system and the functions of the lungs, and causes irritation of the eyes. Inflammation of the respiratory tract causes coughing, mucus secretion, aggravation of asthma and chronic bronchitis and makes people more prone to infections of the respiratory tract. Hospital admissions for cardiac disease and mortality increase on days with higher SO2 levels. When SO2 combines with water, it forms sulfuric acid; this is the main component of acid rain which is a cause of deforestation."

yLab <- "Sulphour Dioxide (ug/m3)"
so2dt <- sotonAirDT[pollutant == "so2"]
t <- so2dt[, .(mean = mean(value, na.rm = TRUE), sd = sd(value, na.rm = TRUE), min = min(value, na.rm = TRUE), 
    max = max(value, na.rm = TRUE)), keyby = .(site)]
kableExtra::kable(t, caption = "Summary of SO2 data") %>% kable_styling()
Table 3.3: Summary of SO2 data
site mean sd min max
Southampton - A33 Roadside (near docks, AURN site) NaN NA Inf -Inf
Southampton - Background (near city centre, AURN site) 5.556158 3.854720 0.10000 30.50000
Southampton - Bitterne NaN NA Inf -Inf
Southampton - Onslow Road (near RSH) NaN NA Inf -Inf
Southampton - Redbridge NaN NA Inf -Inf
Southampton - Victoria Road (Woolston) NaN NA Inf -Inf
Southampton Centre AURN data 3.274498 1.425636 -3.12656 12.51288

Figure 3.3 shows the most recent hourly data.

recentDT <- so2dt[!is.na(value) & obsDate > myParams$recentCutDate]
p <- makeDotPlot(recentDT, xVar = "dateTimeUTC", yVar = "value", byVar = "site", yLab = yLab)

p <- p + scale_x_datetime(date_breaks = "2 day", date_labels = "%a %d %b") + theme(axis.text.x = element_text(angle = 90, 
    hjust = 1)) + labs(caption = paste0(myParams$gamCap, myParams$lockdownCap, myParams$weekendCap))

yMax <- max(recentDT$value)
yMin <- min(recentDT$value)
p <- addLockdownDateTime(p)
addWeekendsDateTime(p)
Sulphour Dioxide levels, Southampton (hourly, recent)

Figure 3.3: Sulphour Dioxide levels, Southampton (hourly, recent)

Beware seasonal trends and weather effects

3.4 Ozone

From WHO: https://www.who.int/news-room/fact-sheets/detail/ambient-(outdoor)-air-quality-and-health

"Ozone at ground level – not to be confused with the ozone layer in the upper atmosphere – is one of the major constituents of photochemical smog. It is formed by the reaction with sunlight (photochemical reaction) of pollutants such as nitrogen oxides (NOx) from vehicle and industry emissions and volatile organic compounds (VOCs) emitted by vehicles, solvents and industry. As a result, the highest levels of ozone pollution occur during periods of sunny weather. Health effects

Excessive ozone in the air can have a marked effect on human health. It can cause breathing problems, trigger asthma, reduce lung function and cause lung diseases. "

yLab <- "Ozone (ug/m3)"
o3dt <- sotonAirDT[pollutant == "o3"]

t <- o3dt[, .(mean = mean(value, na.rm = TRUE), sd = sd(value, na.rm = TRUE), min = min(value, na.rm = TRUE), 
    max = max(value, na.rm = TRUE)), keyby = .(site, source)]
kableExtra::kable(t, caption = "Summary of o3 data") %>% kable_styling()
Table 3.4: Summary of o3 data
site source mean sd min max
Southampton - A33 Roadside (near docks, AURN site) southampton.my-air.uk NaN NA Inf -Inf
Southampton - Background (near city centre, AURN site) southampton.my-air.uk 40.61943 22.03717 0.00000 134.7000
Southampton - Bitterne southampton.my-air.uk NaN NA Inf -Inf
Southampton - Onslow Road (near RSH) southampton.my-air.uk NaN NA Inf -Inf
Southampton - Redbridge southampton.my-air.uk NaN NA Inf -Inf
Southampton - Victoria Road (Woolston) southampton.my-air.uk NaN NA Inf -Inf
Southampton Centre AURN data AURN 52.19365 21.31721 0.74839 104.5747

Table 3.5 suggests that there may be a few (0) negative values.

Figure 3.4 shows the most recent hourly data.

recentDT <- o3dt[!is.na(value) & obsDate > myParams$recentCutDate]
p <- makeDotPlot(recentDT, xVar = "dateTimeUTC", yVar = "value", byVar = "site", yLab = yLab)

p <- p + scale_x_datetime(date_breaks = "2 day", date_labels = "%a %d %b") + theme(axis.text.x = element_text(angle = 90, 
    hjust = 1)) + labs(caption = paste0(myParams$gamCap, myParams$lockdownCap, myParams$weekendCap))

yMax <- max(recentDT$value)
yMin <- min(recentDT$value)
p <- addLockdownDateTime(p)
addWeekendsDateTime(p)
03 levels, Southampton (hourly, recent)

Figure 3.4: 03 levels, Southampton (hourly, recent)

Beware seasonal trends and weather effects

3.5 PM 10

From WHO: https://www.who.int/news-room/fact-sheets/detail/ambient-(outdoor)-air-quality-and-health

"PM is a common proxy indicator for air pollution. It affects more people than any other pollutant. The major components of PM are sulfate, nitrates, ammonia, sodium chloride, black carbon, mineral dust and water. It consists of a complex mixture of solid and liquid particles of organic and inorganic substances suspended in the air. While particles with a diameter of 10 microns or less, (≤ PM10) can penetrate and lodge deep inside the lungs, the even more health-damaging particles are those with a diameter of 2.5 microns or less, (≤ PM2.5). PM2.5 can penetrate the lung barrier and enter the blood system. Chronic exposure to particles contributes to the risk of developing cardiovascular and respiratory diseases, as well as of lung cancer.

There is a close, quantitative relationship between exposure to high concentrations of small particulates (PM10 and PM2.5) and increased mortality or morbidity, both daily and over time. Conversely, when concentrations of small and fine particulates are reduced, related mortality will also go down – presuming other factors remain the same. This allows policy-makers to project the population health improvements that could be expected if particulate air pollution is reduced."

PM 10 data: has more sensors and wider coverage than PM2.5

yLab <- "PM 10 (ug/m3)"
pm10dt <- sotonAirDT[pollutant == "pm10"]

t <- pm10dt[, .(mean = mean(value, na.rm = TRUE), sd = sd(value, na.rm = TRUE), min = min(value, na.rm = TRUE), 
    max = max(value, na.rm = TRUE)), keyby = .(site, source)]
kableExtra::kable(t, caption = "Summary of pm10 data") %>% kable_styling()
Table 3.5: Summary of pm10 data
site source mean sd min max
Southampton - A33 Roadside (near docks, AURN site) southampton.my-air.uk 17.32598 11.387792 0.0 99.000
Southampton - Background (near city centre, AURN site) southampton.my-air.uk 18.69431 11.508593 0.0 252.500
Southampton - Bitterne southampton.my-air.uk NaN NA Inf -Inf
Southampton - Onslow Road (near RSH) southampton.my-air.uk NaN NA Inf -Inf
Southampton - Redbridge southampton.my-air.uk NaN NA Inf -Inf
Southampton - Victoria Road (Woolston) southampton.my-air.uk NaN NA Inf -Inf
Southampton A33 AURN data AURN 18.04088 11.342276 -1.4 95.654
Southampton Centre AURN data AURN 15.93287 9.826833 0.8 76.400

Table 3.5 suggests that there may be a few (1) negative values.

Figure 3.5 shows the most recent hourly data.

recentDT <- pm10dt[!is.na(value) & obsDate > myParams$recentCutDate]
p <- makeDotPlot(recentDT, xVar = "dateTimeUTC", yVar = "value", byVar = "site", yLab = yLab)

p <- p + scale_x_datetime(date_breaks = "2 day", date_labels = "%a %d %b") + theme(axis.text.x = element_text(angle = 90, 
    hjust = 1)) + labs(caption = paste0(myParams$lockdownCap, myParams$weekendCap))

yMax <- max(recentDT$value)
yMin <- min(recentDT$value)
p <- addLockdownDateTime(p)
addWeekendsDateTime(p)
PM10 levels, Southampton (hourly, recent)

Figure 3.5: PM10 levels, Southampton (hourly, recent)

Beware seasonal trends and weather effects

3.6 PM 2.5

From WHO: https://www.who.int/news-room/fact-sheets/detail/ambient-(outdoor)-air-quality-and-health

“Small particulate pollution has health impacts even at very low concentrations – indeed no threshold has been identified below which no damage to health is observed. Therefore, the WHO 2005 guideline limits aimed to achieve the lowest concentrations of PM possible.”

yLab <- "PM 2.5 (ug/m3)"
pm25dt <- sotonAirDT[pollutant == "pm2.5"]
t <- pm25dt[!is.na(value), .(mean = mean(value, na.rm = TRUE), sd = sd(value, na.rm = TRUE), min = min(value, 
    na.rm = TRUE), max = max(value, na.rm = TRUE)), keyby = .(site, source)]
kableExtra::kable(t, caption = "Summary of pm2.5 data") %>% kable_styling()
Table 3.6: Summary of pm2.5 data
site source mean sd min max
Southampton - Background (near city centre, AURN site) southampton.my-air.uk 12.138946 9.732824 0.000 239.100
Southampton Centre AURN data AURN 9.675598 7.340156 0.377 45.755

Table 3.6 suggests that there may be a few (0) negative values.

Figure 3.6 shows the most recent hourly data.

recentDT <- pm25dt[!is.na(value) & obsDate > myParams$recentCutDate]
p <- makeDotPlot(recentDT, xVar = "dateTimeUTC", yVar = "value", byVar = "site", yLab = yLab)

p <- p + scale_x_datetime(date_breaks = "2 day", date_labels = "%a %d %b") + theme(axis.text.x = element_text(angle = 90, 
    hjust = 1)) + labs(caption = paste0(myParams$gamCap, myParams$weekendCap, "\nNB: There is no WHO PM2.5 hourly threshold"))

yMax <- max(recentDT$value)
yMin <- min(recentDT$value)
p <- addLockdownDateTime(p)
addWeekendsDateTime(p)
PM2.5 levels, Southampton (hourly, recent)

Figure 3.6: PM2.5 levels, Southampton (hourly, recent)

Beware seasonal trends and weather effects

4 Annex

4.1 Missing data

Several of these datasets suffer from missing data. This is visualised below.

# dt,xvar, yvar,fillVar, yLab
p <- makeTilePlot(no2dt, xVar = "dateTimeUTC", yVar = "site", fillVar = "value", yLab = yLab)

p
Nitrogen Dioxide data availability and levels over time

Figure 4.1: Nitrogen Dioxide data availability and levels over time

# dt,xvar, yvar,fillVar, yLab
p <- makeTilePlot(noxdt, xVar = "dateTimeUTC", yVar = "site", fillVar = "value", yLab = yLab)

p
Oxides of nitrogen data availability and levels over time

Figure 4.2: Oxides of nitrogen data availability and levels over time

# dt,xvar, yvar,fillVar, yLab
p <- makeTilePlot(so2dt, xVar = "dateTimeUTC", yVar = "site", fillVar = "value", yLab = yLab)

p
Sulphour Dioxide data availability and levels over time

Figure 4.3: Sulphour Dioxide data availability and levels over time

p <- makeTilePlot(o3dt, xVar = "dateTimeUTC", yVar = "site", fillVar = "value", yLab = yLab)

p
Availability and level of o3 data over time

Figure 4.4: Availability and level of o3 data over time

p <- makeTilePlot(pm10dt, xVar = "dateTimeUTC", yVar = "site", fillVar = "value", yLab = yLab)

p
Availability and level of PM 10 data over time

Figure 4.5: Availability and level of PM 10 data over time

p <- makeTilePlot(pm25dt, xVar = "dateTimeUTC", yVar = "site", fillVar = "value", yLab = yLab)

p
Availability and level of PM 10 data over time

Figure 4.6: Availability and level of PM 10 data over time

5 Runtime

Report generated using knitr in RStudio with R version 3.6.3 (2020-02-29) running on x86_64-apple-darwin15.6.0 (Darwin Kernel Version 19.4.0: Wed Mar 4 22:28:40 PST 2020; root:xnu-6153.101.6~15/RELEASE_X86_64).

t <- proc.time() - myParams$startTime

elapsed <- t[[3]]

Analysis completed in 36.943 seconds ( 0.62 minutes).

R packages used:

  • data.table - (Dowle et al. 2015)
  • ggplot2 - (Wickham 2009)
  • here - (Müller 2017)
  • kableExtra - (Zhu 2018)
  • lubridate - (Grolemund and Wickham 2011)
  • skimr - (Arino de la Rubia et al. 2017)
  • viridis - (Garnier 2018)

References

Arino de la Rubia, Eduardo, Hao Zhu, Shannon Ellis, Elin Waring, and Michael Quinn. 2017. Skimr: Skimr. https://github.com/ropenscilabs/skimr.

Dowle, M, A Srinivasan, T Short, S Lianoglou with contributions from R Saporta, and E Antonyan. 2015. Data.table: Extension of Data.frame. https://CRAN.R-project.org/package=data.table.

Garnier, Simon. 2018. Viridis: Default Color Maps from ’Matplotlib’. https://CRAN.R-project.org/package=viridis.

Grolemund, Garrett, and Hadley Wickham. 2011. “Dates and Times Made Easy with lubridate.” Journal of Statistical Software 40 (3): 1–25. http://www.jstatsoft.org/v40/i03/.

Müller, Kirill. 2017. Here: A Simpler Way to Find Your Files. https://CRAN.R-project.org/package=here.

Wickham, Hadley. 2009. Ggplot2: Elegant Graphics for Data Analysis. Springer-Verlag New York. http://ggplot2.org.

Zhu, Hao. 2018. KableExtra: Construct Complex Table with ’Kable’ and Pipe Syntax. https://CRAN.R-project.org/package=kableExtra.